圖片來源:webpack官方文檔
現代化的前端技術與以往不同,不僅是只有基本的HTML、CSS、Javascript,很多時候我們撰寫的內容是需要經由編譯,像是你可能會看到的副檔名包含SASS中的sass或scss、React中的jsx、Vue當中的vue,諸如此類的內容,瀏覽器並沒有辦法理解這些副檔名。甚至有些東西我們希望能夠預先處理後再變成實際網頁渲染的東西,例如將圖片壓縮檔案大小、程式碼刪除空白以便使檔案容量降低,讓眾多的Javascript檔案整合成單一檔案,因此也造就了自動化工具的產生。
Webpack就是處理類似上述事情的前端自動化打包工具。
以下透過列點式的方式列出以下優點
這篇文章將會透過實作編譯sass來從中了解webpack的內容
在實作之前我們先知道幾個核心重點
接下來我們開始實作一個可以編譯sass和自動化生成模板的webpack設定吧
我們預計在src資料夾創建一些檔案如下
├─js
│ index.js
│
└─scss
all.scss
這裡的內容主要放置webpack處理前的內容
npm init -y
npm install webpack webpack-cli --save-dev
接下來要安裝loader
由於js無法理解sass或者css,因此使用loader可以在js當中直接import時候預處理內容,以下指令簡單理解可以說是loader讓webpack讀懂scss,稍後就能在index.js可以import scss檔案。
npm install css-loader sass-loader -D
npm install sass
npm install mini-css-extract-plugin -D
npm install cross-env -D
NODE_ENV
環境變數後再讓webpack自動判別生產環境還是開發環境,然而不同的作業系統要設定環境變數的指令也不太一樣。在linux設定環境變數的指令是是NODE_ENV
在windows則是set NODE_ENV
為了在不同的作業系統上面的指令統一,因此就可以下載cross-env套件解決這樣的問題。
安裝完畢後在package.json的script的部分將腳本設定如下
腳本內容大致意思是 使用cross-env設定環境變數NODE_ENV的值為development
(或production),再執行webpack。
{
//以上省略
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "cross-env NODE_ENV=development webpack",
"deploy": "cross-env NODE_ENV=production webpack"
},
//以下省略
}
設定完畢後,意思是如果我們輸入npm run start
就等同於輸入cross-env NODE_ENV=development webpack
的指令了。
接下來終於來到設定webpack環節,我們預計透過NodeJs的指令process.env
判斷當下的NODE_ENV環境變數,之後再存入到變數中,因此宣告了一個modeEnv的變數。
另外path.resolve是nodeJs的方法,使其透過__dirname
絕對路徑的方式產生dist的資料夾,並且命名叫做bundle.js
。
在rules的部分則是會判斷哪些檔案需要被編譯,透過正規表達式的方式就是sass或scss將其加入規則中,讓webpack抓取的到。
filename: "./css/[contenthash:8].bundle.css",
這段程式碼是plugin撰寫產生8碼的hash值,其原因是當網站重新佈署的時候,使用者的瀏覽器如果再次造訪這個網頁的時候,會發現css檔案不一樣,因此將會重新抓取新的css樣式,換句話說不會因為瀏覽器css暫存的關係讓畫面沒有更新到最新的樣式。
const path = require("path");//引入nodeJs內建的path模組
const modeEnv =
process.env.NODE_ENV === "production" ? "production" : "development";
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: modeEnv,
entry: "./src/js/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
// 把 sass-loader 放在首要處理 (第一步)
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
}, //注意載入順序
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "./css/[contenthash:8].bundle.css",
}),
],
};
在我們剛剛創建的scss資料夾創建all.scss
檔案以及在js資料夾創建index.js
在index.js
的檔案
import "../scss/all.scss";
在all.scss
的檔案
body {
div {
text-align: center;
color: red;
}
}
最後我們在terminal的地方輸入npm run start
,應當能如期看到產生了一個具有8碼hash的css以及bundle.js如下圖
我們嘗試著打開其建置的css檔案可以看到如下的原始碼
/*!************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/scss/all.scss ***!
\************************************************************************************************************/
body div {
text-align: center;
color: red;
}
這是因為我們執行的mode模式是development
我們可以嘗試著改執行npm run deploy
其產生的出的css檔案內容如下
body div{text-align:center;color:red}
換句換說,在production模式的時候webpack會將多餘的空白給刪除達到程式碼最小化以節省檔案大小。
希望透過編譯scss的過程的範例實作能夠理解到webpack一些核心概念和原理,也希望對大家有幫助。